//====================================
// brief: Point类，点的表示类
// author:sunxvming@163.com
// date:  2019-11-15
//====================================

#ifndef NAVMESH_POINT_H
#define NAVMESH_POINT_H

#include <string>

class Point
{
	// 这个类既代表点也代表向量
public:
	double x;
	double y;

public:
	Point(double x, double y);
	Point()
	{
		this->x = 0;
		this->y = 0;
	}
	Point(const Point &p)
	{
		this->x = p.x;
		this->y = p.y;
	}
	
	// 仅适用于两个原始Point的相等比较，要注意double类型的精度丢失问题
	bool operator==(const Point p) { return x == p.x && y == p.y; };
	// std模版使用
	bool operator==(const Point& other) const {
        return x == other.x && y == other.y;
    }
	// 返回Point p到this的向量
	Point operator-(const Point p) { return Point(this->x - p.x, this->y - p.y); };
	// 返回this + 向量p 到达的坐标点
	Point operator+(const Point p) { return Point(this->x + p.x, this->y + p.y); };

	std::string toString() { return "(" + std::to_string(x) + "," + std::to_string(y) + ")"; }

	// 下面这几个成员函数操作的都是向量

	// 向量点积
	double Dot(Point p) { return this->x * p.x + this->y * p.y; };

	// 下面的3个函数利用了向量叉积的几何性质，具体解析图例见文档

	// 向量p在向量this的左侧
	bool inLeft(Point p)
	{
		return (x * p.y - p.x * y) > 0;
	}
	// 向量p在向量this的右侧
	bool inRight(Point p)
	{
		return x * p.y - p.x * y < 0;
	}
	// 两个向量平行，同向或完全反向
	bool inSame(Point p)
	{
		return x * p.y - p.x * y == 0;
	}
	~Point() = default;
};

namespace std {
    template <>
    struct hash<Point> {
		// 用于unordered_set<Point>的哈希处理
        std::size_t operator()(const Point& p) const {
            return std::hash<double>()(p.x) ^ std::hash<double>()(p.y);
        }
    };
}

#endif // NAVMESH_POINT_H
